﻿using Microsoft.Extensions.Logging;
using Puppy.Scheduler.Common;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Text.Json;
using System.Threading;
using System.Threading.Tasks;

namespace Puppy.Scheduler.Processors
{
    /// <summary>
    /// 广播文件清理执行器
    /// </summary>
    public class FileCleanupProcessor : BroadcastProcessor
    {
        protected override Task<ProcessResult> ExecuteAsync(TaskContext context, CancellationToken cancellationToken = default)
        {
            cancellationToken.ThrowIfCancellationRequested();

            Logger.LogInformation("using params {JobParams}", context.JobParams);

            return Task.Factory.StartNew(() =>
            {
                AtomicLong cleanNum = new AtomicLong(0);
                Stopwatch stopwatch = new Stopwatch();
                stopwatch.Start();

                var cleanupParamsList = JsonSerializer.Deserialize<List<CleanupParams>>(context.JobParams);

                foreach (var param in cleanupParamsList)
                {
                    Logger.LogInformation("Start to process {@Param}", param);

                    if (param.FilePattern.IsNullOrEmpty() || param.DirPath.IsNullOrEmpty())
                    {
                        Logger.LogWarning("skip due to invalid param {@Param}", param);
                        continue;
                    }

                    if (!Directory.Exists(param.DirPath))
                    {
                        Logger.LogWarning("skip due to {DirPath} not exixts", param.DirPath);
                        continue;
                    }

                    var files = Directory.GetFiles(param.DirPath, param.FilePattern);
                    Logger.LogInformation($"{param.FilePattern} pattern total file num: {files.Length}");

                    foreach (var file in files)
                    {
                        var fileInfo = new FileInfo(file);
                        if (fileInfo.LastWriteTime > DateTime.Now - param.RetentionTime)
                        {
                            Logger.LogInformation("{File} won't be deleted because it does not meet the time requirement", file);
                            continue;
                        }

                        try
                        {
                            fileInfo.Delete();
                            cleanNum.Increment();
                            Logger.LogInformation("delete {File} successfully!", file);
                        }
                        catch (Exception ex)
                        {
                            Logger.LogError(ex, "delete {File} failed!", file);
                        }
                    }
                }

                stopwatch.Stop();
                return new ProcessResult(true, $"cost:{stopwatch.Elapsed}, clean:{cleanNum.Get()} file");
            });
        }
    }
}
